package service

import (
	"errors"
	"fmt"
	"net/url"
	"strings"
	"time"

	"gitee.com/sansaniot/ssiot-core/facade/env"
	"gitee.com/sansaniot/ssiot-core/httpmvc/service"
	"github.com/gin-gonic/gin"
	"github.com/xuri/excelize/v2"

	"ssalarm/common/constant"
	"ssalarm/common/dto"
	"ssalarm/common/utils"
	"ssalarm/internal/alarm/models"
	"ssalarm/internal/alarm/models/command"
	"ssalarm/internal/alarm/models/query"
)

type SysAlarm struct {
	sysAlarmModel *models.SysAlarm
	service.Service
}

func (d *SysAlarm) SetSysAlarmModel(m *models.SysAlarm) *SysAlarm {
	d.sysAlarmModel = m
	return d
}

func (d *SysAlarm) ProcessAlarm(req *command.AlarmIdReq) (err error) {
	if len(req.Id) == 0 {
		return errors.New("请选择告警记录")
	}
	alarmList := make([]models.SysAlarm, 0)
	where := dto.MakeCondition(query.SysAlarmQuery{IdIn: strings.Split(strings.ReplaceAll(req.Id, " ", ""), ",")})

	//查询要处理的告警记录
	if err = d.sysAlarmModel.FindList(&alarmList, where); err != nil {
		return
	}

	//更新redis状态
	for _, alarm := range alarmList {
		flag := false
		sn := alarm.DevSn
		variable := alarm.VarKey
		redisKey := constant.AlarmConfigKey + sn
		vb, _ := env.Cache.HashGet(redisKey, variable)
		if len(vb) > 0 {
			confArray := utils.BytesToMapArr([]byte(vb))
			for _, confJson := range confArray {
				triggerType := confJson["triggerType"].(float64)
				tmpCount := float64(0)
				if _, ok := confJson["tmpCount"]; ok {
					tmpCount = confJson["tmpCount"].(float64)
				}
				if triggerType == 1 && tmpCount > 0 {
					confJson["tmpCount"] = 0
					flag = true
				}
			}
			if flag {
				vb = string(utils.MapArrToBytes(confArray))
			}
		}
		if flag {
			_ = env.Cache.HashSet(redisKey, variable, vb)
		}
	}
	if err = d.sysAlarmModel.ModMap(d.sysAlarmModel, map[string]interface{}{"process_status": true, "update_time": time.Now(), "suggestion": req.Suggestion}, where); err != nil {
		return
	}
	return
}

func (d *SysAlarm) RemoveAlarmRecord(req *command.AlarmRemoveReq) (err error) {
	delIdList := strings.Split(strings.ReplaceAll(req.Id, " ", ""), ",")
	alarmList := make([]models.SysAlarm, 0)
	where := dto.MakeCondition(query.SysAlarmQuery{IdIn: delIdList})

	//查询要处理的告警记录
	if err = d.sysAlarmModel.FindList(&alarmList, where); err != nil {
		return
	}
	//删除
	if err = d.sysAlarmModel.Delete(d.sysAlarmModel, where); err != nil {
		return
	}
	//更新redis状态
	for _, alarm := range alarmList {
		flag := false
		sn := alarm.DevSn
		variable := alarm.VarKey
		redisKey := constant.AlarmConfigKey + sn
		vb, _ := env.Cache.HashGet(redisKey, variable)
		if len(vb) > 0 {
			confArray := utils.BytesToMapArr([]byte(vb))
			for _, confJson := range confArray {
				triggerType := confJson["triggerType"].(float64)
				tmpCount := float64(0)
				if _, ok := confJson["tmpCount"]; ok {
					tmpCount = confJson["tmpCount"].(float64)
				}
				if triggerType == 1 && tmpCount > 0 {
					var cnt int64
					if err = d.sysAlarmModel.FindCount(d.sysAlarmModel, &cnt, dto.MakeCondition(query.SysAlarmQuery{Sn: sn, Key: variable, ProcessNotDone: true})); err != nil {
						return
					}
					if cnt == 0 {
						// 没了该配置的实时告警了，首次告警重置生效
						confJson["tmpCount"] = 0
						flag = true
					}
				}
			}
			if flag {
				vb = string(utils.MapArrToBytes(confArray))
			}
		}
		if flag {
			_ = env.Cache.HashSet(redisKey, variable, vb)
		}
	}
	return
}

// 导出变量
func (d *SysAlarm) ExportAlarmList(c *gin.Context, req *query.SysAlarmQuery) error {
	req.PageIndex = 0
	alarmList := make([]models.SysAlarm, 0)
	if err, result := d.sysAlarmModel.FindAlarmList(req); err != nil {
		return err
	} else {
		alarmList = result.([]models.SysAlarm)
	}
	if len(alarmList) == 0 {
		return errors.New("查无数据")
	}
	// 生成模板
	f := excelize.NewFile()
	defer f.Close()
	// 模板内容
	if err := FillExportAlarmList(f, alarmList, req.ProcessStatus != nil && !*req.ProcessStatus); err != nil {
		return err
	}
	// 删除excelize的默认sheet
	f.DeleteSheet("Sheet1")
	// 响应文件流
	fileName := fmt.Sprintf("告警监控.xlsx")
	c.Header("Content-Disposition", fmt.Sprintf("attachment; filename*=utf-8''%s", url.QueryEscape(fileName)))
	c.Header("File-Name", url.QueryEscape(fileName))
	c.Header("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8")
	if _, err := f.WriteTo(c.Writer); err != nil {
		_, _ = fmt.Fprintf(c.Writer, err.Error())
		return err
	}
	return nil
}
